﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Caching;
using System.Text;
using System.Threading.Tasks;

namespace King.Box.CacheProvider
{
    public class MemoryCacheProvider
    {
        private MemoryCache _cache;
        private static object _lock = new object();
        private static MemoryCacheProvider _instance;

        private MemoryCacheProvider()
        {
            _cache = MemoryCache.Default;
        }

        public static MemoryCacheProvider Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (_lock)
                    {
                        if (_instance == null)
                            _instance = new MemoryCacheProvider();
                    }
                }

                return _instance;
            }
        }

        public bool Exists(string key)
        {
            if (string.IsNullOrEmpty(key))
                return false;

            return _cache.Contains(key);
        }

        public bool Add(string key, object value, DateTimeOffset? expriseIn = null)
        {
            if (!expriseIn.HasValue)
                expriseIn = DateTimeOffset.Now.AddHours(2);

            return _cache.Add(key, value, expriseIn.Value);
        }

        public bool Remove(string key)
        {
            _cache.Remove(key);

            return !this.Exists(key);
        }

        public void Remove(IEnumerable<string> keys)
        {
            if (keys == null || keys.Count() <= 0)
                return;

            keys.ToList().ForEach(x =>
            {
                _cache.Remove(x);
            });
        }

        public object Get(string key)
        {
            return _cache.Get(key);
        }

        public T Get<T>(string key) where T : class
        {
            return _cache.Get(key) as T;
        }

        public bool ListAdd(string key, object value, DateTimeOffset? expriseIn = null)
        {
            if (!expriseIn.HasValue)
                expriseIn = DateTimeOffset.Now.AddHours(2);

            var currentList = Get(key) as List<object>;
            currentList.Add(value);
            return Add(key, currentList);
        }

        public bool ListAddRange(string key, List<object> value, DateTimeOffset? expriseIn = null)
        {
            if (!expriseIn.HasValue)
                expriseIn = DateTimeOffset.Now.AddHours(2);

            var currentList = Get(key) as List<object>;
            currentList.Add(value);
            return Add(key, currentList);
        }

        public bool RemoveListItem(string key, object value)
        {
            var currentList = Get(key) as List<object>;
            currentList.Remove(value);
            return Add(key, currentList);
        }

        public bool RemoveListItem(string key, IEnumerable<object> values)
        {
            var currentList = Get(key) as List<object>;
            values.ToList().ForEach(x =>
            {
                currentList.Remove(x);
            });

            return Add(key, currentList);
        }
    }
}
